home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS11.ADF
/
Modula-2
/
CaseConvert
/
symbols.mod
< prev
next >
Wrap
Text File
|
1986-08-05
|
4KB
|
163 lines
(*
MODULE - Symbols.
The symbol table is a hash table. The collisions are
resolved by using a hash table with chaining
Created: 3/26/85 by Richie Bielak
Modified: 4/2/86 by Richie Bielak
- Create heap required on the Amiga.
- Use procedures from "String" module.
Copyright (c) 1986 - by Richie Bielak
This program maybe freely copied, but please leave my name in.
Thanks....Richie
*)
IMPLEMENTATION MODULE Symbols;
FROM Terminal IMPORT WriteString, WriteLn;
FROM Storage IMPORT ALLOCATE, CreateHeap;
FROM String IMPORT Length;
CONST
TableSize = 1001; (* This should be a prime *)
BufferSize = 1024 * 4; (* Size of character buffer *)
TYPE
(* Types for character buffers *)
CharBuffer = ARRAY [1..BufferSize] OF CHAR;
CharBufferPtr = POINTER TO CharBuffer;
NodePtr = POINTER TO Node;
Node = RECORD
Next : NodePtr;
Index : CARDINAL; (* Index in the buffer *)
END;
VAR
HashTable : ARRAY [0..TableSize-1] OF NodePtr;
BuffPtr : CharBufferPtr;
CurrentBufPos : CARDINAL;
(* Hash the symbol - but ignore the case *)
PROCEDURE Hash (VAR S : ARRAY OF CHAR; Len : CARDINAL) : CARDINAL;
VAR
h, i : CARDINAL;
BEGIN
h := ORD(CAP(S[0]));
FOR i := 1 TO Len-1 DO
h := (h * 4 + ORD(CAP(S[i]))) MOD TableSize;
END;
RETURN h
END Hash;
(* Insert a new symbol. User must worry about uniqueness *)
PROCEDURE InsertSymbol (VAR Symbol : ARRAY OF CHAR);
VAR
Len : CARDINAL;
temp : NodePtr;
i : CARDINAL;
(* This procedure stores a string in the buffer *)
PROCEDURE StoreString (VAR S : ARRAY OF CHAR; Len : CARDINAL);
VAR
i : CARDINAL;
BEGIN
(* Now store the string *)
FOR i := 0 TO Len-1 DO
BuffPtr^[CurrentBufPos + i] := S[i];
END;
INC(CurrentBufPos, Len);
(* Mark the end of string with a null character *)
BuffPtr^[CurrentBufPos] := 0C; INC(CurrentBufPos);
END StoreString;
BEGIN
Len := Length (Symbol);
IF Len > 0 THEN
(* If the current buffer is full, crash!! *)
IF (CurrentBufPos + Len) > BufferSize THEN
WriteString ("**** Buffer overflow "); WriteLn; HALT
END;
(* Make a new node *)
NEW (temp);
temp^.Index := CurrentBufPos;
(* Store the string *)
StoreString(Symbol, Len);
(* Finally insert it in the hash table *)
i := Hash (Symbol, Len);
WITH temp^ DO
Next := HashTable[i]; HashTable[i] := temp
END;
END
END InsertSymbol;
(* Find a symbol, and return it in the form it occurs in the table *)
PROCEDURE FindSymbol (VAR KeySymbol : ARRAY OF CHAR;
VAR RetSymbol : ARRAY OF CHAR) : BOOLEAN;
VAR
Len, i : CARDINAL;
temp : NodePtr;
Found : BOOLEAN;
(* Compare an array to a string in a buffer - ingnore case *)
PROCEDURE Equal (VAR S : ARRAY OF CHAR; Len : CARDINAL; Ptr : NodePtr)
: BOOLEAN;
VAR
i : CARDINAL;
BEGIN
(* Symbols must be the same length to be equal *)
(* The symbol in the buffer starts at position *)
(* "Ptr^.Index", so "Len" characters from it *)
(* there should be a NULL. *)
IF BuffPtr^[Ptr^.Index + Len] <> 0C THEN RETURN FALSE END;
FOR i := 0 TO Len-1 DO
IF CAP(S[i]) <> CAP(BuffPtr^[Ptr^.Index+i]) THEN RETURN FALSE END
END;
RETURN TRUE
END Equal;
BEGIN
Found := FALSE;
(* First hash the key *)
Len := Length (KeySymbol);
IF Len > 0 THEN
i := Hash (KeySymbol,Len);
temp := HashTable[i];
(* Now search the list *)
WHILE (temp <> NIL) AND (NOT Equal(KeySymbol,Len,temp)) DO
temp := temp^.Next
END;
(* If we found it, copy the symbol to the output variable *)
IF temp <> NIL THEN
FOR i := 0 TO Len DO (* By going until "len" we also copy the Null *)
RetSymbol[i] := BuffPtr^[temp^.Index+i]
END; (* FOR *)
Found := TRUE
END
END;
RETURN Found
END FindSymbol;
VAR
i : CARDINAL;
BEGIN (* Main *)
(* Create a heap *)
IF NOT CreateHeap (BufferSize * 4) THEN
WriteString ("Symbols-- unable to create heap "); WriteLn; HALT
END;
(* Initialize *)
FOR i := 0 TO TableSize-1 DO HashTable[i] := NIL END;
(* Allocate a buffer for the strings *)
CurrentBufPos := 1;
NEW (BuffPtr);
END Symbols.